package by.bsu.diploma.ga;

import by.bsu.diploma.common.Grid;
import by.bsu.diploma.common.Word;

import java.util.ArrayList;
import java.util.List;
import static by.bsu.diploma.common.Constants.INTERSECTION;
import static by.bsu.diploma.common.Orientation.VERTICAL;

/**
 * @author Anatoly Selitsky
 */
public class Genome implements Comparable<Genome> {

    private Grid grid;
    private List<Word> words = new ArrayList<Word>();
    private int fitness;

    public Genome(Grid grid) {
        this.grid = grid;
        this.fitness = calcFitness();
    }

    public Genome(Grid grid, List<Word> words) {
        this.grid = grid;
        this.words = words;
        this.fitness = calcFitness();
    }

    public Grid getGrid() {
        return grid;
    }

    public int getFitness() {
        return fitness;
    }

    private int calcFitness() {
        int fitness = 0, crossingCount = 0, cells[][] = grid.getCells();
        for (int i = 0; i < grid.getRowCount(); i++) {
            for (int j = 0; j < grid.getColumnCount(); j++) {
                if (cells[i][j] == INTERSECTION) {
                    crossingCount++;
                }
            }
        }
        int size = words.size();
        if (size > 0) {
            if (crossingCount == size - 1) {
                fitness += 10 * size;
            }
        } else {
            fitness += 100;
        }
        for (Word word : words) {
            int row = word.getRow(), col = word.getCol(), length = word.getLength(), count = 0;
            boolean first = false, last = false;
            if (VERTICAL.equals(word.getOrientation())) {
                for (int i = row; i < row + length; i++) {
                    if (cells[i][col] == INTERSECTION) {
                        if (i == row) {
                            first = true;
                        }
                        if (i == row + length - 1) {
                            last = true;
                        }
                        count++;
                    }
                }
            } else {
                for (int i = col; i < col + length - 1; i++) {
                    if (cells[row][i] == INTERSECTION) {
                        if (i == col) {
                            first = true;
                        }
                        if (i == col + length - 1) {
                            last = true;
                        }
                        count++;
                    }
                }
            }
            if (count == 0) {
                fitness += 15 * length;
            } else if (first || last) {
                if (count == 1) {
                    fitness += 10 * length;
                }
            } else if (count == 1) {
                fitness += 5 * length;
            }
        }
        return fitness;
    }

    @Override
    public int compareTo(Genome genome) {
        return this.fitness - genome.getFitness();
    }

    @Override
    public String toString() {
        StringBuilder builder = new StringBuilder();
        builder.append("fitness = ")
               .append(fitness)
               .append("\n")
               .append(grid);
        return builder.toString();
    }

}
